# Corrected simulation of the wave algorithm

class Node:
    def __init__(self, node_id):
        self.node_id = node_id
        self.neighbors = []
        self.parent = None
        self.received_messages = 0
        self.decision_made = False

    def add_neighbor(self, neighbor_node):
        self.neighbors.append(neighbor_node)

    def send_wave(self):
        print(f"Node {self.node_id} sends a wave message to its neighbor(s)")
        for neighbor in self.neighbors:
            neighbor.receive_wave(self)

    def receive_wave(self, from_node):
        self.received_messages += 1
        if not self.parent:
            self.parent = from_node
            print(f"Node {self.node_id} receives a wave message from Node {from_node.node_id} and assigns it as its parent")
            # After receiving wave from its parent, it sends out waves to its other neighbors
            for neighbor in self.neighbors:
                if neighbor != from_node:
                    neighbor.receive_wave(self)

    def make_decision_and_notify(self):
        if not self.decision_made and self.received_messages == len(self.neighbors):
            self.decision_made = True
            print(f"Node {self.node_id} decides and sends notification to its neighbor(s)")
            for neighbor in self.neighbors:
                neighbor.receive_notification(self)

    def receive_notification(self, from_node):
        # Receiving a decision notification from a neighbor
        if self.decision_made:
            # Already made a decision, just pass on the notification
            print(f"Node {self.node_id} receives a notification from Node {from_node.node_id} and halts")
        else:
            # If not yet made a decision, wait until a decision is made
            self.received_messages += 1
            if self.received_messages == len(self.neighbors):
                self.make_decision_and_notify()

# Initialize nodes
nodes = [Node(i) for i in range(1, 7)]

# Setup neighbors
neighbors = {1: [3], 2: [3], 3: [1, 2, 4], 4: [3, 5, 6], 5: [4], 6: [4]}
for node_id, neighbor_ids in neighbors.items():
    node = nodes[node_id - 1]
    for neighbor_id in neighbor_ids:
        node.add_neighbor(nodes[neighbor_id - 1])

# Start the wave messages from leaf nodes
leaf_nodes = [node for node in nodes if len(node.neighbors) == 1]
for leaf_node in leaf_nodes:
    leaf_node.send_wave()

# After waves are sent, each node checks if it can make a decision
for node in nodes:
    node.make_decision_and_notify()

